﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PlutoStudio.Net.Messages
{
    internal class MessageQueue
    {
        private int capacity;
        private byte[] buffer;
        private int _length;
        private int _position;
        public MessageQueue()
            : this(8192)
        {

        }

        public MessageQueue(int capacity)
        {
            this.capacity = capacity;
            this._length = 0;
            this._position = 0;
            buffer = new byte[capacity];
            Array.Clear(buffer, 0, capacity);
        }

        public void Write(byte[] buffer)
        {
            Write(buffer, 0);
        }

        public void Write(byte[] buffer, int offset)
        {
            Write(buffer, offset, buffer.Length - offset);
        }

        public void Write(byte[] buffer, int offset, int count)
        {
            lock (this.buffer)
            {
                var num = this._length + count;
                if (num > this.capacity)
                {
                    this.EnsureCapacity(num);
                }
                Buffer.BlockCopy(buffer, offset, this.buffer, _length, count);
                _length += count;
            }
        }

        public Message Read()
        {
            lock (this.buffer)
            {
                var message = Message.FromBuffer(buffer,_length);
                if (message!=null)
                {
                    _position += message.Size;
                    ResetPosition(); 
                }
                return message;
            }
        }

        private void ResetPosition()
        {
            Buffer.BlockCopy(this.buffer, _position, this.buffer, 0, _length - _position);
            this._length -= _position;
            _position = 0;
            Array.Clear(this.buffer, _length, buffer.Length - _length);
        }

        public void Clear()
        {
            _position = 0;
            _length = 0;
            Array.Clear(this.buffer, 0, buffer.Length);
        }

        private bool EnsureCapacity(int value)
        {
            if (value <= this.capacity)
            {
                return false;
            }
            int num = value;
            if (num < 256)
            {
                num = 256;
            }
            if (num < (this.capacity * 2))
            {
                num = this.capacity * 2;
            }
            this.Capacity = num;
            return true;
        }

        public virtual int Capacity
        {
            get
            {
                return (this.capacity);
            }
            private set
            {
                if (value != this.capacity)
                {
                    if (value > 0)
                    {
                        byte[] dst = new byte[value];
                        if (this._length > 0)
                        {
                            Buffer.BlockCopy(this.buffer, 0, dst, 0, this._length);
                        }
                        this.buffer = dst;
                    }
                    else
                    {
                        this.buffer = null;
                    }
                    this.capacity = value;
                }
            }
        }
    }
}
